#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>

/**
 * @brief 测试统计结构
 */
struct TestStats {
    int total = 0;
    int passed = 0;
    int failed = 0;
    int skipped = 0;
};

static TestStats g_stats;

/**
 * @brief 错误处理函数
 * @param msg 错误消息
 */
static void die(const char *msg) {
    int err = errno;
    fprintf(stderr, "[%d] %s\n", err, msg);
    abort();
}

/**
 * @brief 从缓冲区读取32位整数
 * @param buf 缓冲区
 * @return 32位整数
 */
static uint32_t read_le32(const uint8_t *buf) {
    uint32_t val = 0;
    memcpy(&val, buf, 4);
    return val;
}

/**
 * @brief 向缓冲区写入32位整数
 * @param buf 缓冲区
 * @param val 32位整数
 */
static void write_le32(uint8_t *buf, uint32_t val) {
    memcpy(buf, &val, 4);
}

/**
 * @brief 从缓冲区读取64位整数
 * @param buf 缓冲区
 * @return 64位整数
 */
static uint64_t read_le64(const uint8_t *buf) {
    uint64_t val = 0;
    memcpy(&val, buf, 8);
    return val;
}

/**
 * @brief 从缓冲区读取双精度浮点数
 * @param buf 缓冲区
 * @return 双精度浮点数
 */
static double read_dbl(const uint8_t *buf) {
    double val = 0;
    memcpy(&val, buf, 8);
    return val;
}

/**
 * @brief 序列化类型
 */
enum {
    SER_NIL = 0,    // 空值
    SER_ERR = 1,    // 错误码 + 消息
    SER_STR = 2,    // 字符串
    SER_INT = 3,    // int64
    SER_DBL = 4,    // double
    SER_ARR = 5,    // 数组
};

/**
 * @brief 读取完整数据
 * @param fd 文件描述符
 * @param buf 缓冲区
 * @param n 要读取的字节数
 * @return 成功返回0，失败返回-1
 */
static int32_t read_full(int fd, char *buf, size_t n) {
    while (n > 0) {
        ssize_t rv = read(fd, buf, n);
        if (rv <= 0) {
            return -1;  // 错误或EOF
        }
        assert((size_t)rv <= n);
        n -= (size_t)rv;
        buf += rv;
    }
    return 0;
}

/**
 * @brief 写入完整数据
 * @param fd 文件描述符
 * @param buf 缓冲区
 * @param n 要写入的字节数
 * @return 成功返回0，失败返回-1
 */
static int32_t write_all(int fd, const char *buf, size_t n) {
    while (n > 0) {
        ssize_t rv = write(fd, buf, n);
        if (rv <= 0) {
            return -1;  // 错误
        }
        assert((size_t)rv <= n);
        n -= (size_t)rv;
        buf += rv;
    }
    return 0;
}

/**
 * @brief 发送请求到服务器
 * @param fd 文件描述符
 * @param cmd 命令向量
 * @return 成功返回0，失败返回-1
 */
static int32_t send_req(int fd, const std::vector<std::string> &cmd) {
    uint32_t len = 4;
    for (const std::string &s : cmd) {
        len += 4 + s.size();
    }
    if (len > 4096) {
        return -1;
    }

    char wbuf[4 + 4096];
    write_le32((uint8_t *)&wbuf[0], len);
    write_le32((uint8_t *)&wbuf[4], cmd.size());
    size_t cur = 8;
    for (const std::string &s : cmd) {
        write_le32((uint8_t *)&wbuf[cur], s.size());
        memcpy(&wbuf[cur + 4], s.data(), s.size());
        cur += 4 + s.size();
    }

    uint32_t total_len = len + 4;
    return write_all(fd, wbuf, total_len) == 0 ? 0 : -1;
}

/**
 * @brief 解析响应数据
 * @param data 响应数据
 * @param len 数据长度
 * @param pos 当前位置
 * @return 解析成功返回0，失败返回-1
 */
static int32_t parse_response(const uint8_t *data, uint32_t len, uint32_t &pos) 
{
    if (pos >= len) 
    {
        return -1;
    }

    switch (data[pos++]) {
    case SER_NIL:
        printf("(nil)");
        return 0;
    case SER_ERR:
        if (pos + 8 > len) {
            return -1;
        }
        {
            int32_t code = 0;
            uint32_t msg_len = 0;
            memcpy(&code, &data[pos], 4);
            memcpy(&msg_len, &data[pos + 4], 4);
            pos += 8;
            if (pos + msg_len > len) {
                return -1;
            }
            printf("(err) %d %.*s", code, msg_len, &data[pos]);
            pos += msg_len;
        }
        return 0;
    case SER_STR:
        if (pos + 4 > len) {
            return -1;
        }
        {
            uint32_t str_len = read_le32(&data[pos]);
            pos += 4;
            if (pos + str_len > len) {
                return -1;
            }
            printf("(str) \"%.*s\"", str_len, &data[pos]);
            pos += str_len;
        }
        return 0;
    case SER_INT:
        if (pos + 8 > len) {
            return -1;
        }
        {
            int64_t val = (int64_t)read_le64(&data[pos]);
            pos += 8;
            printf("(int) %ld", val);
        }
        return 0;
    case SER_DBL:
        if (pos + 8 > len) {
            return -1;
        }
        {
            double val = read_dbl(&data[pos]);
            pos += 8;
            printf("(dbl) %g", val);
        }
        return 0;
    case SER_ARR:
        if (pos + 4 > len) {
            return -1;
        }
        {
            uint32_t arr_len = read_le32(&data[pos]);
            pos += 4;
            printf("(arr) len=%u", arr_len);
            for (uint32_t i = 0; i < arr_len; ++i) {
                printf(" [%u] ", i);
                if (parse_response(data, len, pos) != 0) {
                    return -1;
                }
            }
        }
        return 0;
    default:
        return -1;
    }
}

/**
 * @brief 读取服务器响应
 * @param fd 文件描述符
 * @return 成功返回0，失败返回-1
 */
static int32_t read_res(int fd) {
    // 读取4字节长度头
    char rbuf[4 + 4096 + 1];
    errno = 0;
    int32_t err = read_full(fd, rbuf, 4);
    if (err != 0) {
        return err;
    }

    uint32_t len = read_le32((uint8_t *)rbuf);
    if (len > 4096) {
        return -1;
    }

    // 读取响应主体
    err = read_full(fd, &rbuf[4], len);
    if (err != 0) {
        return -1;
    }

    // 解析并显示响应
    uint32_t pos = 4;
    int32_t rv = parse_response((uint8_t *)rbuf, 4 + len, pos);
    if (rv != 0) {
        return -1;
    }
    if (pos != 4 + len) {
        return -1;
    }
    return 0;
}

/**
 * @brief 执行单个命令
 * @param fd 文件描述符
 * @param cmd_line 命令行
 * @param test_name 测试名称
 */
static void exec_command(int fd, const std::string &cmd_line, const std::string &test_name) {
    if (cmd_line.empty() || cmd_line[0] == '#') {
        return; // 跳过注释和空行
    }

    // 解析命令 - 处理带引号的参数
    std::vector<std::string> cmd;
    std::string current_arg;
    bool in_quotes = false;
    bool escape_next = false;
    
    for (size_t i = 0; i < cmd_line.length(); ++i) {
        char c = cmd_line[i];
        
        if (escape_next) {
            current_arg += c;
            escape_next = false;
        } else if (c == '\\') {
            escape_next = true;
        } else if (c == '"') {
            in_quotes = !in_quotes;
        } else if (c == ' ' && !in_quotes) {
            if (!current_arg.empty()) {
                cmd.push_back(current_arg);
                current_arg.clear();
            }
        } else {
            current_arg += c;
        }
    }
    
    if (!current_arg.empty()) {
        cmd.push_back(current_arg);
    }
    
    if (cmd.empty()) {
        return;
    }

    g_stats.total++;
    
    printf("🔍 测试 %d: %s\n", g_stats.total, test_name.c_str());
    printf("   命令: %s\n", cmd_line.c_str());
    printf("   解析: ");
    for (size_t i = 0; i < cmd.size(); ++i) {
        printf("[%s]", cmd[i].c_str());
        if (i < cmd.size() - 1) printf(" ");
    }
    printf("\n   响应: ");
    
    // 发送命令
    if (send_req(fd, cmd) != 0) {
        printf("❌ 发送失败\n");
        g_stats.failed++;
        return;
    }
    
    // 读取响应
    if (read_res(fd) != 0) {
        printf("❌ 读取失败\n");
        g_stats.failed++;
        return;
    }
    
    printf(" ✅\n\n");
    g_stats.passed++;
}

/**
 * @brief 分割字符串为命令参数
 * @param input 输入字符串
 * @return 分割后的参数向量
 */
static std::vector<std::string> split_command(const std::string &input) {
    std::vector<std::string> args;
    std::istringstream iss(input);
    std::string arg;
    
    while (iss >> arg) {
        args.push_back(arg);
    }
    
    return args;
}

/**
 * @brief 主函数
 */
int main() {
    printf("🚀 Redis服务器自动化功能测试\n");
    printf("================================\n\n");

    // 连接到服务器
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        die("socket()");
    }

    struct sockaddr_in addr = {};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(1234);
    addr.sin_addr.s_addr = ntohl(INADDR_LOOPBACK);  // 127.0.0.1
    
    int rv = connect(fd, (const struct sockaddr *)&addr, sizeof(addr));
    if (rv) {
        die("连接失败，请确保Redis服务器正在运行");
    }

    printf("✅ 已连接到Redis服务器 (127.0.0.1:1234)\n\n");

    // 定义测试命令
    std::vector<std::pair<std::string, std::string>> test_commands = {
        // 基本字符串操作测试
        {"SET key1 value1", "基本SET操作"},
        {"GET key1", "基本GET操作"},
        {"SET key2 hello", "设置多个键值对1"},
        {"SET key3 world", "设置多个键值对2"},
        {"SET key4 redis", "设置多个键值对3"},
        {"KEYS", "获取所有键"},
        {"GET nonexistent", "获取不存在的键"},
        {"SET key1 newvalue", "覆盖已存在的键"},
        {"GET key1", "验证键值覆盖"},
        
        // 中文字符支持测试
        {"SET 中文键 中文值", "中文键值对"},
        {"GET 中文键", "获取中文键值"},
        {"SET name 张三", "混合中英文1"},
        {"SET 姓名 李四", "混合中英文2"},
        {"GET name", "获取混合中英文1"},
        {"GET 姓名", "获取混合中英文2"},
        
        // 特殊字符处理测试
        {"SET empty \"\"", "空字符串"},
        {"GET empty", "获取空字符串"},
        {"SET spaced \"hello world\"", "包含空格的值"},
        {"GET spaced", "获取包含空格的值"},
        {"SET special \"!@#$%^&*()\"", "特殊符号"},
        {"GET special", "获取特殊符号"},
        {"SET number \"12345\"", "数字字符串"},
        {"GET number", "获取数字字符串"},
        
        // 键管理测试
        {"DEL key2", "删除键"},
        {"GET key2", "验证键删除"},
        {"DEL nonexistent", "删除不存在的键"},
        {"DEL 中文键", "删除中文键"},
        
        // 有序集合操作测试
        {"ZADD myzset 1.0 member1", "创建有序集合1"},
        {"ZADD myzset 2.0 member2", "创建有序集合2"},
        {"ZADD myzset 3.0 member3", "创建有序集合3"},
        {"ZSCORE myzset member1", "获取成员分数1"},
        {"ZSCORE myzset member2", "获取成员分数2"},
        {"ZSCORE myzset member3", "获取成员分数3"},
        {"ZSCORE myzset nonexistent", "获取不存在成员分数"},
        {"ZADD myzset 2.5 member1", "更新成员分数"},
        {"ZSCORE myzset member1", "验证分数更新"},
        {"ZQUERY myzset 0 \"\" 0 10", "查询有序集合"},
        {"ZQUERY myzset 2.0 \"\" 0 5", "按分数范围查询"},
        {"ZREM myzset member2", "删除有序集合成员"},
        {"ZSCORE myzset member2", "验证成员删除"},
        
        // 中文有序集合
        {"ZADD 中文集合 1.5 成员1", "中文有序集合1"},
        {"ZADD 中文集合 2.5 成员2", "中文有序集合2"},
        {"ZSCORE 中文集合 成员1", "获取中文成员分数"},
        {"ZQUERY 中文集合 0 \"\" 0 10", "查询中文有序集合"},
        
        // TTL过期机制测试
        {"SET temp_key temp_value", "设置临时键"},
        {"PEXPIRE temp_key 5000", "设置5秒过期时间"},
        {"PTTL temp_key", "检查过期时间"},
        {"GET temp_key", "获取临时键值"},
        {"SET short_key short_value", "设置短期键"},
        {"PEXPIRE short_key 2000", "设置2秒过期时间"},
        {"PTTL short_key", "检查短期过期时间"},
        
        // 错误处理测试
        {"INVALID_COMMAND", "无效命令测试"},
        {"SET", "参数不足测试1"},
        {"GET", "参数不足测试2"},
        {"ZADD myzset", "参数不足测试3"},
        {"ZSCORE myzset", "参数不足测试4"},
        {"SET string_key string_value", "设置字符串键"},
        {"ZADD string_key 1.0 member", "类型错误测试1"},
        {"ZSCORE string_key member", "类型错误测试2"},
        
        // 混合数据类型测试
        {"SET str1 value1", "混合类型测试1"},
        {"SET str2 value2", "混合类型测试2"},
        {"ZADD zset1 1.0 member1", "混合类型测试3"},
        {"ZADD zset2 2.0 member2", "混合类型测试4"},
        {"KEYS", "查看所有键"},
        {"GET str1", "验证字符串1"},
        {"GET str2", "验证字符串2"},
        {"ZSCORE zset1 member1", "验证有序集合1"},
        {"ZSCORE zset2 member2", "验证有序集合2"},
        
        // 批量数据测试
        {"SET bulk1 data1", "批量数据1"},
        {"SET bulk2 data2", "批量数据2"},
        {"SET bulk3 data3", "批量数据3"},
        {"ZADD bulkzset 1.0 item1", "批量有序集合1"},
        {"ZADD bulkzset 2.0 item2", "批量有序集合2"},
        {"ZADD bulkzset 3.0 item3", "批量有序集合3"},
        {"ZQUERY bulkzset 0 \"\" 0 10", "批量查询测试"},
        
        // 边界条件测试
        {"SET very_long_key_name_that_tests_limits very_long_value", "长键名测试"},
        {"ZADD precision_test 3.14159265359 pi", "浮点精度测试1"},
        {"ZADD precision_test 2.71828182846 e", "浮点精度测试2"},
        {"ZSCORE precision_test pi", "验证π值"},
        {"ZSCORE precision_test e", "验证e值"},
        
        // 最终检查
        {"KEYS", "最终键列表检查"}
    };

    // 执行所有测试
    for (const auto &test : test_commands) {
        exec_command(fd, test.first, test.second);
        usleep(10000); // 10ms延迟，避免过快请求
    }

    // 输出测试结果
    printf("🎯 测试完成统计\n");
    printf("================\n");
    printf("总测试数: %d\n", g_stats.total);
    printf("通过数量: %d\n", g_stats.passed);
    printf("失败数量: %d\n", g_stats.failed);
    printf("跳过数量: %d\n", g_stats.skipped);
    printf("成功率: %.1f%%\n", g_stats.total > 0 ? (double)g_stats.passed / g_stats.total * 100 : 0);
    
    if (g_stats.failed == 0) {
        printf("\n🎉 所有测试通过！Redis服务器功能完整！\n");
    } else {
        printf("\n⚠️  有 %d 个测试失败，请检查服务器实现\n", g_stats.failed);
    }

    close(fd);
    return g_stats.failed == 0 ? 0 : 1;
} 